/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package it.txt.access.capability.demo.service.impl;

import it.txt.access.capability.demo.service.ICapabilityAuthDemoService;
import it.txt.access.capability.demo.service.CapabilityAuthDemoServiceException;
import it.txt.access.capability.commons.signer.model.X509DocumentSignerInfo;
import it.txt.access.capability.demo.schema.request.factory.CapabilityDemoRequestFactory;
import it.txt.access.capability.factory.CapabilitySchemaFactory;
import it.txt.access.capability.factory.CapabilitySchemaFactoryException;
import it.txt.access.capability.commons.signer.model.X509CertificateKeyValues;
import it.txt.access.capability.commons.signer.X509DocumentSigner;
import it.txt.access.capability.commons.utils.ClientServerUtils;
import it.txt.access.capability.demo.schema.CapabilityRequestType;
import it.txt.access.capability.demo.schema.CapabilityResponseType;
import it.txt.access.capability.demo.schema.factory.CapabilityDemoFactoryException;
import it.txt.access.capability.demo.schema.response.factory.CapabilityDemoResponseFactory;
import it.txt.access.capability.demo.service.model.ServerResponseInfoModel;
import it.txt.access.capability.demo.service.model.ServiceRequestInfoModel;
import java.security.GeneralSecurityException;
import javax.xml.transform.dom.DOMSource;
import org.w3c.dom.Document;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
 *
 * @author seccia
 */
public class CapabilityAuthDemoServiceImpl implements ICapabilityAuthDemoService {

    private static final Logger LOGGER = Logger.getLogger(CapabilityAuthDemoServiceImpl.class.getName());
    private X509CertificateKeyValues certificateKeyValues;

    public CapabilityAuthDemoServiceImpl(String schemasPath, X509DocumentSignerInfo signerInfo)
            throws CapabilitySchemaFactoryException,
            CapabilityDemoFactoryException, GeneralSecurityException {
        CapabilitySchemaFactory.getInstance(schemasPath);
        CapabilityDemoRequestFactory.getInstance(schemasPath);
        CapabilityDemoResponseFactory.getInstance(schemasPath);
        certificateKeyValues = X509DocumentSigner.getCertificateKeyValues(signerInfo);
        LOGGER.log(Level.INFO, "Capability Auth Demo ServiceKeystore Data - "
                + "Using Server ID: " + "{0}", signerInfo.getSignerID());
    }

    public CapabilityResponseType capabilityRequestService(CapabilityRequestType crt) throws CapabilityAuthDemoServiceException {
        //init a new server response info model
        ServerResponseInfoModel responseInfoModel = new ServerResponseInfoModel();
        //the response message sent to the client
        String responseMessage = "";
        try {
            //check the received client request.
            ServiceRequestInfoModel requestInfoModel = checkCapabilityAuthRequest(crt);
            //Strore the request ID into the response info model.
            responseInfoModel.setRequestID(requestInfoModel.getRequestID());
            //Store the vslid request status into the response info model.
            responseMessage += ClientServerUtils.RESPONSE_CAPABILITY_VALID;
            try {
                //Now try to perform the requested operation
                CapabilityAuthDemoServiceHelper.performRequestOperation(requestInfoModel);
                //The operation was performed. Append to the status response
                //the operation performed message.
                responseMessage += " " + ClientServerUtils.RESPONSE_REQUEST_OPERATION_PERFORMED;
            } catch (CapabilityAuthDemoRequestOptException ex) {
                //The request contains an invalid operation.
                LOGGER.log(Level.SEVERE, ex.getMessage(), ex);
                //Store the error response status into the response info model.
                responseMessage += " " + ex.getMessage();
            }
        } catch (CapabilityAuthDemoRequestException ex) {
            //The request contains an invalid capability.
            LOGGER.log(Level.SEVERE, ex.getMessage(), ex);
            //Store invalid request ID into the response info model.
            responseInfoModel.setRequestID(ClientServerUtils.INVALID_REQUEST_ID);
            //Store the error response status into the response info model.
            responseMessage = ClientServerUtils.RESPONSE_CAPABILITY_INVALID;
            responseMessage += " " + ex.getMessage();
        }
        //Store the final request status into the response info model.
        responseInfoModel.setResponseStatus(responseMessage);
        try {
            //Prepare the signed response to the client and recover the response ID.
            return createCapabilityAuthResponse(responseInfoModel);
        } catch (CapabilityDemoFactoryException ex) {
            throw new CapabilityAuthDemoServiceException(ex.getMessage(), ex);
        } catch (GeneralSecurityException ex) {
            throw new CapabilityAuthDemoServiceException(ex.getMessage(), ex);
        }
    }

    private ServiceRequestInfoModel checkCapabilityAuthRequest(CapabilityRequestType crt) throws CapabilityAuthDemoRequestException {
        //Request received now get the cabaility request and make controls.
        ServiceRequestInfoModel requestInfoModel = null;
        LOGGER.log(Level.INFO, "Verifying request capability...");
        requestInfoModel = CapabilityAuthDemoServiceHelper.checkRequestCapability(crt);
        //Recover the request ID.
        String requestID = requestInfoModel.getRequestID();
        LOGGER.log(Level.INFO, "Capability Verify OK. - Request ID: {0}", requestID);
        return requestInfoModel;
    }

    private CapabilityResponseType createCapabilityAuthResponse(ServerResponseInfoModel infoModel)
            throws CapabilityDemoFactoryException, GeneralSecurityException {
        //Creating the signed xml response
        CapabilityResponseType responseType =
                CapabilityDemoResponseFactory.getInstance().createResponse(
                infoModel.getResponseStatus(), infoModel.getRequestID());
        Document signedResponseDoc =
                CapabilityDemoResponseFactory.getInstance().createResponseDocument(
                responseType);
        X509DocumentSigner.signXMLElement(signedResponseDoc.getDocumentElement(),
                certificateKeyValues, CapabilityDemoResponseFactory.SIGN_DOCUMENT_AFTER_NODE);
        return CapabilityDemoResponseFactory.getInstance().createResponse(
                new DOMSource(signedResponseDoc));
    }
}
